package com.tsugun.mediaplayer.presenter.service

import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.media.AudioManager
import android.media.MediaPlayer
import android.os.Bundle
import android.os.PowerManager
import android.support.v4.app.NotificationManagerCompat
import android.support.v4.media.MediaBrowserCompat
import android.support.v4.media.MediaBrowserServiceCompat
import android.support.v4.media.session.MediaButtonReceiver
import android.support.v4.media.session.MediaSessionCompat
import android.support.v4.media.session.PlaybackStateCompat
import android.util.Log

import com.tsugun.mediaplayer.R
import com.tsugun.mediaplayer.model.entity.MusicModel
import com.tsugun.mediaplayer.presenter.manager.MediaNotificationCompatManager
import com.tsugun.mediaplayer.presenter.provider.ListProvider
import com.tsugun.mediaplayer.presenter.utils.SettingPreferenceHelper
import com.tsugun.mediaplayer.view.activity.BaseActivity
import com.tsugun.mediaplayer.view.activity.LockActivity

import java.io.IOException
import java.util.ArrayList
import java.util.Random

import com.tsugun.mediaplayer.presenter.utils.ConverterHelper.PLAY_MODE_LIST_LOOP
import com.tsugun.mediaplayer.presenter.utils.ConverterHelper.PLAY_MODE_ONE_LOOP
import com.tsugun.mediaplayer.presenter.utils.ConverterHelper.PLAY_MODE_RANDOM_LOOP
import com.tsugun.mediaplayer.presenter.utils.LogHelper.TAG

/**
 * 音乐服务
 * Created by shize on 2017/6/20.
 */

class MusicAudioService : MediaBrowserServiceCompat(), AudioManager.OnAudioFocusChangeListener,
        MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {

    private var mProvider: ListProvider? = null
    // 播放列表
    private var mPlayList: MutableList<MusicModel>? = null

    private var mMediaSessionCompat: MediaSessionCompat? = null
    private var mStateBuilder: PlaybackStateCompat.Builder? = null
    private var mCompatManager: MediaNotificationCompatManager? = null

    private var mMediaPlayer: MediaPlayer? = null // 媒体播放器
    private var mNoisyReceiver: NoisyReceiver? = null // 耳机监听广播
    private var mLockReceiver: LockScreenReceiver? = null // 锁屏监听广播
    private var mMode: Int = 0 // 循环播放模式

    override fun onCreate() {
        super.onCreate()
        initData()
        initMediaPlayer()
        initMediaSession()
        initNoisyReceiver()
        initLockReceiver()
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        // 将传递到服务的intent传送到MediaButtonReceiver类中
        MediaButtonReceiver.handleIntent(mMediaSessionCompat, intent)
        return super.onStartCommand(intent, flags, startId)
    }

    /**
     * 初始化数据
     */
    private fun initData() {
        mCurrentPosition = 0
        mMode = PLAY_MODE_LIST_LOOP
        mProvider = BaseActivity.getMusicProvider()
        mState = PlaybackStateCompat.STATE_STOPPED
        mPlayList = ArrayList<MusicModel>()
    }

    /**
     * 初始化MediaPlayer
     */
    private fun initMediaPlayer() {
        if (mMediaPlayer != null) {
            mMediaPlayer!!.reset()
            return
        }
        mMediaPlayer = MediaPlayer()
        mMediaPlayer!!.setWakeMode(applicationContext, PowerManager.PARTIAL_WAKE_LOCK)// 唤醒模式
        mMediaPlayer!!.setAudioStreamType(AudioManager.STREAM_MUSIC) // 音频流类型
        mMediaPlayer!!.setVolume(1.0f, 1.0f) // 左右音频播放音量
        mMediaPlayer!!.setOnCompletionListener(this)
        mMediaPlayer!!.setOnErrorListener(this)
    }

    /**
     * 注册广播用于监听耳机变化
     */
    private fun initNoisyReceiver() {
        mNoisyReceiver = NoisyReceiver()
        val filter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
        registerReceiver(mNoisyReceiver, filter)
    }

    /**
     * 初始化锁屏广播接收器
     */
    private fun initLockReceiver() {
        mLockReceiver = LockScreenReceiver()
        val intentFilter = IntentFilter(Intent.ACTION_SCREEN_OFF)
        registerReceiver(mLockReceiver, intentFilter)
    }

    /**
     * 初始化MediaSession,并将其连接到媒体按钮和控制方法
     */
    private fun initMediaSession() {
        val mediaButtonReceiver = ComponentName(applicationContext,
                MediaButtonReceiver::class.java)

        // 服务会话令牌
        val mediaButtonIntent = Intent(Intent.ACTION_MEDIA_BUTTON)
        mediaButtonIntent.setClass(this, MediaButtonReceiver::class.java)
        val pendingIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, 0)

        mMediaSessionCompat = MediaSessionCompat(applicationContext, TAG_SESSION,
                mediaButtonReceiver, null)
        mMediaSessionCompat!!.setCallback(SessionCallback())
        mMediaSessionCompat!!.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS)
        mMediaSessionCompat!!.setMediaButtonReceiver(pendingIntent)
        sessionToken = mMediaSessionCompat!!.sessionToken
        mCompatManager = MediaNotificationCompatManager(this)
    }

    override fun onGetRoot(clientPackageName: String, clientUid: Int, rootHints: Bundle?): MediaBrowserServiceCompat.BrowserRoot? {
        return MediaBrowserServiceCompat.BrowserRoot(getString(R.string.app_name), null)
    }

    override fun onLoadChildren(parentId: String, result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>) {
        result.sendResult(null)
    }

    /**
     * 音频焦点监听
     */
    override fun onAudioFocusChange(focusChange: Int) {
        when (focusChange) {
        // 这发生在另一个应用程序请求音频焦点。发生这种情况时，您应该停止在应用程式中播放音讯。
            AudioManager.AUDIOFOCUS_LOSS -> {
                if (mMediaPlayer!!.isPlaying) {
                    mMediaPlayer!!.stop()
                }
            }
        // 当另一个应用程序想播放音频时输入此状态，但它只预计需要短时间的聚焦。
        // 您可以使用此状态暂停音频播放。
            AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
                mMediaPlayer!!.pause()
            }
        // 当请求音频焦点，但抛出“可以鸭子”状态，这意味着您可以继续播放，
        // 但应该使音量下降一点。这可能在设备播放通知声音时发生。
            AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
                if (mMediaPlayer != null) {
                    mMediaPlayer!!.setVolume(0.3f, 0.3f)
                }
            }
        // 我们将讨论的最终状态是AUDIOFOCUS_GAIN。这是可达的音频播放完成时的状态，
        // 您的应用程序可以恢复其以前的级别。
            AudioManager.AUDIOFOCUS_GAIN -> {
                if (mMediaPlayer != null) {
                    if (!mMediaPlayer!!.isPlaying) {
                        mMediaPlayer!!.start()
                    }
                    mMediaPlayer!!.setVolume(1.0f, 1.0f)
                }
            }
        }
    }

    override fun onCompletion(mp: MediaPlayer) {
        // 当前歌曲播放完成调用
        Log.e(TAG, "onCompletion: ")
        when (mMode) {
            PLAY_MODE_ONE_LOOP -> onOneLoopModeCompletion()
            PLAY_MODE_LIST_LOOP -> onListLoopModeCompletion()
            PLAY_MODE_RANDOM_LOOP -> onRandomModeCompletion()
        }
    }

    /**
     * 单曲循环模式下播放
     */
    private fun onOneLoopModeCompletion() {
        mCurrentPosition--
        skipToNext()
    }

    /**
     * 列表循环模式下播放
     */
    private fun onListLoopModeCompletion() {
        skipToNext()
    }

    /**
     * 随机播放下播放
     */
    private fun onRandomModeCompletion() {
        if (mPlayList!!.size < 2) {
            skipToNext()
            return
        }
        var random = Random().nextInt(mPlayList!!.size)
        while (random == mCurrentPosition) {
            random = Random().nextInt(mPlayList!!.size)
        }
        mCurrentPosition = random - 1
        skipToNext()
    }

    override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean {
        // 播放错误时调用
        Log.e(TAG, "onError: ")
        if (mMediaPlayer != null) {
            // 释放资源
            mMediaPlayer!!.release()
        }
        return false
    }

    override fun onDestroy() {
        super.onDestroy()
        val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
        audioManager.abandonAudioFocus(this)
        unregisterReceiver(mNoisyReceiver)
        unregisterReceiver(mLockReceiver)
        mMediaSessionCompat!!.release()
        NotificationManagerCompat.from(this).cancel(1)
        mCompatManager!!.stopNotification()
    }

    /**
     * 检测获取焦点是否成功
     */
    fun successfullyRetrievedAudioFocus(): Boolean {
        val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
        val result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
                AudioManager.AUDIOFOCUS_GAIN)
        return result == AudioManager.AUDIOFOCUS_GAIN
    }

    /**
     * 设置播放状态

     * @param state 状态[PlaybackStateCompat]
     */
    fun setMediaPlaybackState(state: Int) {
        mStateBuilder = PlaybackStateCompat.Builder()
        if (state == PlaybackStateCompat.STATE_PLAYING) {
            mStateBuilder!!.setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE or PlaybackStateCompat.ACTION_PAUSE)
        } else {
            mStateBuilder!!.setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE or PlaybackStateCompat.ACTION_PLAY)
        }
        mStateBuilder!!.setState(state, PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, 0f)
        mMediaSessionCompat!!.setPlaybackState(mStateBuilder!!.build())
    }

    /**
     * Session回调
     */
    private inner class SessionCallback : MediaSessionCompat.Callback() {

        override fun onPlay() {
            super.onPlay()
            Log.e(TAG, "onPlay: ")
            // 处理音频焦点
            if (!successfullyRetrievedAudioFocus()) {
                return
            }
            if (mState != PlaybackStateCompat.STATE_PAUSED) {
                play()
                return
            }
            mMediaPlayer!!.start()
            mState = PlaybackStateCompat.STATE_PLAYING
            setMediaPlaybackState(mState)
        }

        override fun onPause() {
            super.onPause()
            Log.e(TAG, "onPause: ")
            pause()
        }

        override fun onSeekTo(pos: Long) {
            super.onSeekTo(pos)
            seekTo(pos)
        }

        override fun onSkipToNext() {
            super.onSkipToNext()
            skipToNext()
        }

        override fun onSkipToPrevious() {
            super.onSkipToPrevious()
            skipToPrevious()
        }

        override fun onStop() {
            super.onStop()
            stop()
        }

        override fun onSkipToQueueItem(id: Long) {
            super.onSkipToQueueItem(id)
            skipToQueueItem(id)
        }

        override fun onCustomAction(action: String?, extras: Bundle?) {
            super.onCustomAction(action, extras)
            when (action) {
                CUSTOM_ACTION_MODE_CHANGE -> {
                    mMode = extras!!.getInt(EXTRAS_MODE)
                    Log.d(TAG, "onCustomAction: mode=" + mMode)
                }
            }
        }
    }

    /**
     * 开始播放歌曲
     */
    private fun play() {
        if (!hasPlayMusic()) return
        val musicModel = mPlayList!![mCurrentPosition]
        mMediaSessionCompat!!.setMetadata(musicModel.mediaMetadataCompat)
        try {
            mMediaPlayer!!.reset()
            mMediaPlayer!!.setDataSource(musicModel.url)
            mMediaPlayer!!.prepare()
        } catch (e: IOException) {
            e.printStackTrace()
        }

        mMediaSessionCompat!!.isActive = true
        setMediaPlaybackState(PlaybackStateCompat.STATE_PLAYING)
        mCompatManager!!.startNotification()
        mMediaPlayer!!.start()
        mState = PlaybackStateCompat.STATE_PLAYING
        // 添加进历史播放列表
        mProvider!!.setLately(musicModel.id)
    }

    /**
     * 暂停播放
     */
    private fun pause() {
        if (mMediaPlayer!!.isPlaying) {
            mMediaPlayer!!.pause()
            setMediaPlaybackState(PlaybackStateCompat.STATE_PAUSED)
            mCompatManager!!.startNotification()
        }
        mState = PlaybackStateCompat.STATE_PAUSED
    }

    /**
     * 跳转到歌曲的指定时间

     * @param pos 目标时间
     */
    private fun seekTo(pos: Long) {
        Log.d(TAG, "onSeekTo: position=" + pos)
        mMediaPlayer!!.seekTo(pos.toInt())
    }

    /**
     * 播放上一首歌曲
     */
    private fun skipToPrevious() {
        if (!hasPlayMusic()) return
        Log.d(TAG, "onSkipToPrevious: ")
        mCurrentPosition--
        if (mCurrentPosition < 0) {
            mCurrentPosition = mPlayList!!.size - 1
        }
        stopPlayer()
        play()
    }

    /**
     * 播放下一首歌曲
     */
    private fun skipToNext() {
        if (!hasPlayMusic()) return
        Log.d(TAG, "onSkipToNext: ")
        mCurrentPosition++
        if (mCurrentPosition > mPlayList!!.size - 1) {
            mCurrentPosition = 0
        }
        stopPlayer()
        play()
    }

    /**
     * 停止播放器
     */
    private fun stopPlayer() {
        if (mMediaPlayer != null) {
            mMediaPlayer!!.stop()
        }
    }

    /**
     * 跳转到播放列表的指定位置

     * @param id 指定位置
     */
    private fun skipToQueueItem(id: Long) {
        if (!hasPlayMusic()) {
            return
        }
        if (id < mPlayList!!.size && id >= 0) {
            mCurrentPosition = id.toInt()
        }
        stopPlayer()
        play()
    }

    /**
     * 停止播放
     */
    private fun stop() {
        Log.d(TAG, "onStop: ")
        stopPlayer()
        mMediaPlayer!!.release()
    }

    /**
     * 确认播放列表是否还有音乐
     */
    private fun hasPlayMusic(): Boolean {
        mPlayList!!.clear()
        mPlayList!!.addAll(mProvider!!.playList as Collection<MusicModel>)
        if (mPlayList!!.size < 1) {
            Log.e(TAG, "play: 播放列表中没有音乐！")
            mMediaPlayer!!.reset()
            mCurrentPosition = 0
            mState = PlaybackStateCompat.STATE_STOPPED
            setMediaPlaybackState(mState)
            return false
        }
        return true
    }

    /**
     * 接受耳机变化的广播
     */
    private inner class NoisyReceiver : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent) {
            if (mMediaPlayer != null && mMediaPlayer!!.isPlaying) {
                mMediaPlayer!!.pause()
            }
        }
    }

    /**
     * 锁屏接收广播，熄灭屏幕广播
     */
    private inner class LockScreenReceiver : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action == Intent.ACTION_SCREEN_OFF) {
                // 熄屏
                Log.d(TAG, "onReceive: 接收到锁屏广播！！！")
                if (SettingPreferenceHelper.getLockScreenSetting(this@MusicAudioService)) {
                    startLockScreen()
                }
            }
        }

        /**
         * 启动锁屏
         */
        private fun startLockScreen() {
            // 没有播放的歌曲时不开启锁屏
            if (mState == PlaybackStateCompat.STATE_STOPPED) {
                return
            }
            val intent = Intent(this@MusicAudioService, LockActivity::class.java)
            // 在Service中启动activity时需要新启动一个任务栈
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            intent.putExtra(LockActivity.EXTRA_MUSIC_ID, mPlayList!![mCurrentPosition].id)
            startActivity(intent)
        }
    }

    companion object {

        val TAG_SESSION = "com.TsuGun.MediaPlayer.tag.session"
        // 自定义动作
        val CUSTOM_ACTION_MODE_CHANGE = "custom.action.mode.change"
        // 自定义动作bundle的key
        val EXTRAS_MODE = "mode"
        var mCurrentPosition: Int = 0 // 当前播放位置
        var mState: Int = 0 // 播放状态
    }


    /*
     * 显示通知
     */
    //    public void showPlayingNotification() {
    //        NotificationCompat.Builder builder = getNotificationBuilder(mPlayList.get(mCurrentPosition));
    //        if (builder == null) {
    //            return;
    //        }
    //        builder.addAction(new NotificationCompat.Action(android.R.drawable.ic_media_pause, "Pause",
    //                MediaButtonReceiver.buildMediaButtonPendingIntent(this,
    //                        PlaybackStateCompat.ACTION_PLAY_PAUSE)));
    //        builder.setStyle(new android.support.v7.app.NotificationCompat.MediaStyle()
    //                .setShowActionsInCompactView(0).setMediaSession(mMediaSessionCompat.getSessionToken()));
    //        builder.setSmallIcon(R.drawable.ic_favorite_light);
    //        NotificationManagerCompat.from(this).notify(1, builder.build());
    //    }
    //
    //    private void showPausedNotification() {
    //        NotificationCompat.Builder builder = getNotificationBuilder(mPlayList.get(mCurrentPosition));
    //        if (builder == null) {
    //            return;
    //        }
    //        builder.addAction(new NotificationCompat.Action(android.R.drawable.ic_media_play, "Play",
    //                MediaButtonReceiver.buildMediaButtonPendingIntent(this,
    //                        PlaybackStateCompat.ACTION_PLAY_PAUSE)));
    //        builder.setStyle(new android.support.v7.app.NotificationCompat.MediaStyle()
    //                .setShowActionsInCompactView(0).setMediaSession(mMediaSessionCompat.getSessionToken()));
    //        builder.setSmallIcon(R.drawable.ic_favorite_light);
    //        NotificationManagerCompat.from(this).notify(1, builder.build());
    //    }
    //
    //    /**
    //     * 生成通知Builder
    //     */
    //    public NotificationCompat.Builder getNotificationBuilder(MusicModel musicModel) {
    //        MediaControllerCompat controller = mMediaSessionCompat.getController();
    //
    //        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
    //        builder.setContentTitle(musicModel.getTitle())
    //                .setContentText(musicModel.getArtist())
    //                .setSubText(musicModel.getAlbum())
    //                .setLargeIcon(BitmapFactory.decodeFile(musicModel.getImageUrl()))
    //                .setContentIntent(controller.getSessionActivity())
    //                .setDeleteIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(this,
    //                        PlaybackStateCompat.ACTION_STOP))
    //                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
    //
    //        return builder;
    //    }
}
